package com.self.av;

import android.app.Activity;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.ActivityInfo;
import android.content.res.Configuration;
import android.graphics.Bitmap;
import android.graphics.Canvas;
import android.graphics.Color;
import android.graphics.Matrix;
import android.graphics.PointF;
import android.media.MediaFormat;
import android.media.MediaMetadataRetriever;
import android.net.Uri;
import android.os.Build;
import android.os.Bundle;
import android.os.Environment;
import android.os.Handler;
import android.os.Looper;
import android.os.SystemClock;
import android.util.Log;
import android.view.GestureDetector;
import android.view.Gravity;
import android.view.LayoutInflater;
import android.view.MotionEvent;
import android.view.TextureView;
import android.view.View;
import android.widget.Button;
import android.widget.CheckBox;
import android.widget.FrameLayout;
import android.widget.ImageView;
import android.widget.PopupWindow;
import android.widget.SeekBar;
import android.widget.TextView;
import android.widget.Toast;

import androidx.activity.result.ActivityResultLauncher;
import androidx.activity.result.contract.ActivityResultContracts;
import androidx.annotation.NonNull;
import androidx.annotation.Nullable;
import androidx.annotation.OptIn;
import androidx.appcompat.app.AppCompatActivity;
import androidx.core.content.ContextCompat;
import androidx.media3.common.Format;
import androidx.media3.common.MediaItem;
import androidx.media3.common.PlaybackParameters;
import androidx.media3.common.Player;
import androidx.media3.common.TrackSelectionParameters;
import androidx.media3.common.util.UnstableApi;
import androidx.media3.datasource.cache.CacheDataSource;
import androidx.media3.exoplayer.DefaultRenderersFactory;
import androidx.media3.exoplayer.ExoPlayer;
import androidx.media3.exoplayer.RenderersFactory;
import androidx.media3.exoplayer.source.MediaSource;
import androidx.media3.exoplayer.source.ProgressiveMediaSource;
import androidx.media3.exoplayer.trackselection.DefaultTrackSelector;
import androidx.media3.exoplayer.trackselection.TrackSelector;
import androidx.media3.exoplayer.video.VideoFrameMetadataListener;
import androidx.media3.ui.PlayerView;

import com.google.mediapipe.framework.image.BitmapImageBuilder;
import com.google.mediapipe.framework.image.MPImage;
import com.google.mediapipe.tasks.components.containers.NormalizedLandmark;
import com.google.mediapipe.tasks.core.BaseOptions;
import com.google.mediapipe.tasks.core.Delegate;
import com.google.mediapipe.tasks.core.OutputHandler;
import com.google.mediapipe.tasks.vision.core.RunningMode;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarker;
import com.google.mediapipe.tasks.vision.poselandmarker.PoseLandmarkerResult;

import org.json.JSONArray;
import org.json.JSONObject;

import java.io.BufferedReader;
import java.io.File;
import java.io.FileReader;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;

public class VideoPlayerActivity extends AppCompatActivity {
    private GestureDetector gestureDetector;
    private ImageView magnifierImageView;
    private PopupWindow popupWindow;
    private PopupWindow drawPopupWindow;
    private DrawView drawView;
    private Button settingsButton;
    private Button drawSettingsButton;
//    private Button decreaseSpeedButton;
//    private Button increaseSpeedButton;
    private ExoPlayer player;
    private SeekBar seekBar;
//    private TextView playTextView;
    private TextView replayTextView;
    private Button lastFrameButton;
    private Button nextFrameButton;
    private Button replayTagButton;
    private Button playPauseButton;
    private Button replayButton;
    private final Handler handler = new Handler(Looper.getMainLooper());
    private PlayerView playerView;
    private com.self.av.GridOverlayView gridOverlayView;
    private ActionLineView actionLineView;
    private ImageView freezeImageView;
    private ImageView coverImageView;
    private PoseLandmarker poseLandmarker;
    private TextView playbackRateTextView;
    private TextView seekBarBackground;
    private TextView leftShoulderTextView;
    private TextView rightShoulderTextView;
    private TextView leftElbowTextView;
    private TextView rightElbowTextView;
    private static final float[] speedList = new float[]{0.2f, 0.4f, 0.6f, 0.8f, 1.0f, 1.2f, 1.4f, 1.6f, 1.8f, 2.0f, 2.2f, 2.4f, 2.6f, 2.8f, 3.0f};
    private int currentSpeedIdx = 4;
    private boolean isWaiting = false;
    private Uri videoUri;
    private int totalFrames;
    private long currentPresentationTimeUs = 0;
    private float frameRate = 0;

//    private float initialX;
//    private float initialY;
//    private long initialPosition;
    private int moveStatus = 0;
    private int frameWidth = 0;
    private int frameHeight = 0;
    private long replayStartTime = -1;
    private long replayEndTime = -1;
    private boolean isReplay = false;
    private Bitmap originalVideoBitmap = null;
    private static final float MAGNIFICATION_FACTOR = 3.0f; // 放大倍数
    private static final int MAGNIFIER_SIZE = 100; // 放大镜截取区域大小

    private static final int NONE = 0;
    private static final int DRAG = 1;
    private static final int ZOOM = 2;
    private int mode = NONE;
    private float oldDist = 1f;
    private float scale = 1f;
    private static final float MIN_SCALE = 1f;
    private static final float MAX_SCALE = 5f;
    private float lastX = 0;
    private float lastY = 0;
    private float dx = 0;
    private float dy = 0;
    private float initialScale = 1f; // 初始缩放比例
    private float initialTranslationX = 0f; // 初始 X 轴偏移量
    private float initialTranslationY = 0f; // 初始 Y 轴偏移量
    private ExecutorService detectionExecutorService;
    private Future<?> currentDetectionTask; // 用于跟踪当前的检测任务
    private HashMap<Integer, List<NormalizedLandmark>> preprocessData = new HashMap<>();
    ActivityResultLauncher<Intent> preprocessActivityLauncher;

    private List<List<NormalizedLandmark>> previousLandmarks = new ArrayList<>();
    private static final String[] JOINT_NAMES = {
            "Nose", "Left Eye", "Right Eye", "Left Ear", "Right Ear",
            "Left Shoulder", "Right Shoulder", "Left Elbow", "Right Elbow",
            "Left Wrist", "Right Wrist", "Left Hip", "Right Hip",
            "Left Knee", "Right Knee", "Left Ankle", "Right Ankle"
    };
//    private static final int[] PAIR_IDS = {
//            11, 12, 13, 14,
//            15, 16, 23, 24,
//    };
    private HashMap<Integer, Boolean> nodeStates = new HashMap<>();

    private SharedPreferences sharedPreferences;
    private final Handler checkSharedPrefsHandler = new Handler(Looper.getMainLooper());
    private final Runnable checkSharedPrefsRunnable = new Runnable() {
        @Override
        public void run() {
            boolean shouldProcessFrame = sharedPreferences.getBoolean("shouldProcessFrame", false);
            if (shouldProcessFrame) {
                getNodeState();
                processFrame();
                SharedPreferences.Editor editor = sharedPreferences.edit();
                editor.putBoolean("shouldProcessFrame", false); // 重置标记
                editor.apply();
            }
            checkSharedPrefsHandler.postDelayed(this, 100); // 每 100 毫秒检查一次
        }
    };

    private final Runnable updateSeekBarRunnable = new Runnable() {
        @Override
        public void run() {
            if (player != null) {
                long currentPosition = player.getCurrentPosition();
                if (isReplay && player.isPlaying()) {
                    if (currentPosition >= replayEndTime){
                        isReplay = false;
                        playerPause();
                    }
                }
                long duration = player.getDuration();
                if (duration > 0) {
                    int progress = (int) (((float)currentPosition / (float)duration)  * 100.0f);
                    seekBar.setProgress(progress);
                }
                handler.postDelayed(this, 10); // 每秒更新一次
            }
        }
    };
    private final Handler longPressHandler = new Handler(Looper.getMainLooper());
    private final Runnable forwardRunnable = new Runnable() {
        @OptIn(markerClass = UnstableApi.class) @Override
        public void run() {
            Log.e("@@@@@forwardRunnable", "run: " + isWaiting);
            if (player != null && !isWaiting) {
                isWaiting = true;
                long p = player.getCurrentPosition() + (long) (1000 / player.getVideoFormat().frameRate);
                player.seekTo(p);
            }
            longPressHandler.postDelayed(this, 100); // 每 0.5 秒执行一次
        }
    };

    private final Runnable backwardRunnable = new Runnable() {
        @OptIn(markerClass = UnstableApi.class) @Override
        public void run() {
            Log.e("@@@@@backwardRunnable", "run: " + isWaiting);
            if (player != null && !isWaiting) {
                isWaiting = true;
                long p = player.getCurrentPosition() - (long) (1000 / player.getVideoFormat().frameRate);
                player.seekTo(p);
            }
            longPressHandler.postDelayed(this, 100); // 每 0.5 秒执行一次
        }
    };

    public void getNodeState() {
        for (Map.Entry<Integer, Boolean> entry : nodeStates.entrySet()) {
            int index = entry.getKey();
            boolean isEnabled = sharedPreferences.getBoolean(index + "", true);
            nodeStates.put(index, isEnabled);
        }
    }

    @OptIn(markerClass = UnstableApi.class) @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_video_player);
        nodeStates.put(0, true);
        nodeStates.put(11, true);
        nodeStates.put(12, true);
        nodeStates.put(13, true);
        nodeStates.put(14, true);
        nodeStates.put(15, true);
        nodeStates.put(16, true);
        nodeStates.put(23, true);
        nodeStates.put(24, true);

        // 获取传递过来的参数
        // 获取视频文件 Uri
        String videoUriStr = getIntent().getStringExtra("videoUri");
        String selectedModel = getIntent().getStringExtra("selectedModel");
        sharedPreferences = getSharedPreferences("VideoPlayerPrefs", MODE_PRIVATE);
        SharedPreferences.Editor editor = sharedPreferences.edit();
        editor.putString("selectedModel", selectedModel);
        editor.apply();

        getNodeState();

        detectionExecutorService = Executors.newFixedThreadPool(5);
        loadMPModel(selectedModel);

        CacheDataSource.Factory cacheDataSourceFactory = CacheManager.getCacheDataSourceFactory(this);

        RenderersFactory renderersFactory = new DefaultRenderersFactory(this)
                .setExtensionRendererMode(DefaultRenderersFactory.EXTENSION_RENDERER_MODE_PREFER);

        actionLineView = findViewById(R.id.actionLineView);
        playerView = findViewById(R.id.playerView);
        settingsButton = findViewById(R.id.settingsButton);
        gridOverlayView = findViewById(R.id.gridOverlayView);
        coverImageView = findViewById(R.id.coverImageView);
        playbackRateTextView = findViewById(R.id.playbackRateTextView);
        coverImageView.setBackgroundColor(Color.rgb(125, 125, 125));
//        playTextView = findViewById(R.id.playTextView);
        replayTagButton = findViewById(R.id.replayTagButton);
        playPauseButton = findViewById(R.id.playPauseButton);
        replayButton = findViewById(R.id.replayButton);
        replayTextView = findViewById(R.id.replayTextView);
        drawView = findViewById(R.id.drawView);
        magnifierImageView = findViewById(R.id.magnifierImageView);
//        decreaseSpeedButton = findViewById(R.id.decreaseSpeedButton);
//        increaseSpeedButton = findViewById(R.id.increaseSpeedButton);
        seekBarBackground = findViewById(R.id.seekBarBackground);
        leftShoulderTextView = findViewById(R.id.leftShoulderTextView);
        rightShoulderTextView = findViewById(R.id.rightShoulderTextView);
        leftElbowTextView = findViewById(R.id.leftElbowTextView);
        rightElbowTextView = findViewById(R.id.rightElbowTextView);
//        CheckBox paintModeCheckbox = findViewById(R.id.paintModeCheckbox);
//        Button clearDrawButton = findViewById(R.id.clearDrawButton);
        drawSettingsButton = findViewById(R.id.drawSettingsButton);

        playPauseButton.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.teal_200));
        playPauseButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (playPauseButton.getText().toString().equals("暂停")) {
                    playerPause();
                } else {
                    if (player.getCurrentPosition() >= player.getDuration()){
                        player.seekTo(0);
                    }
                    playerPlay();
                }
            }
        });

        // 加载下拉菜单布局
        View popupView = LayoutInflater.from(this).inflate(R.layout.popup_menu, null);
        CheckBox hideLandmarkerCheckbox = popupView.findViewById(R.id.hideLandmarkerCheckbox);
        CheckBox hideGridCheckbox = popupView.findViewById(R.id.hideGridCheckbox);
        CheckBox hideVideoCheckbox = popupView.findViewById(R.id.hideVideoCheckbox);
        CheckBox freezeCheckbox = popupView.findViewById(R.id.freezeCheckbox);
        CheckBox showPathCheckbox = popupView.findViewById(R.id.showPathCheckbox);
        CheckBox landscapeCheckbox = popupView.findViewById(R.id.landscapeCheckbox);
        Button customNodeButton = popupView.findViewById(R.id.customNodeButton);
        Button preprocessButton = popupView.findViewById(R.id.preprocessButton);
        Button decreaseSpeedButton = popupView.findViewById(R.id.decreaseSpeedButton);
        Button increaseSpeedButton = popupView.findViewById(R.id.increaseSpeedButton);

        // 创建 PopupWindow
        popupWindow = new PopupWindow(
                popupView,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                true
        );
        popupWindow.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.dialog_holo_light_frame));
        popupWindow.setOutsideTouchable(true);

        // 加载下拉菜单布局
        View drawPopupView = LayoutInflater.from(this).inflate(R.layout.draw_popup_menu, null);
        CheckBox paintModeCheckbox = drawPopupView.findViewById(R.id.paintModeCheckbox);
        CheckBox lineModeCheckbox = drawPopupView.findViewById(R.id.lineModeCheckbox);
        Button clearDrawButton = drawPopupView.findViewById(R.id.clearDrawButton);

        drawPopupWindow = new PopupWindow(
                drawPopupView,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                android.view.ViewGroup.LayoutParams.WRAP_CONTENT,
                true
        );
        drawPopupWindow.setBackgroundDrawable(getResources().getDrawable(android.R.drawable.dialog_holo_light_frame));
        drawPopupWindow.setOutsideTouchable(true);

        // 设置 CheckBox 点击事件
        hideLandmarkerCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                actionLineView.setShowAction(false);
            } else {
                actionLineView.setShowAction(true);
            }
        });

        hideGridCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                gridOverlayView.setVisibility(View.INVISIBLE);
            } else {
                gridOverlayView.setVisibility(View.VISIBLE);
            }
        });

        hideVideoCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                coverImageView.setVisibility(View.VISIBLE);
            } else {
                coverImageView.setVisibility(View.INVISIBLE);
            }
        });

        freezeCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                Bitmap frameBitmap = getFrameBitmap(player.getCurrentPosition() * 1000);
                freezeImageView.setImageBitmap(frameBitmap);
                freezeImageView.setVisibility(View.VISIBLE);
            } else {
//                freezeImageView.setImageBitmap(null);
                freezeImageView.setVisibility(View.INVISIBLE);
            }
        });

        showPathCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                actionLineView.setShowPath(true);
            } else {
                actionLineView.clearPathPoints();
            }
        });

        landscapeCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                // 切换到横屏模式
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_LANDSCAPE);
            } else {
                // 切换到竖屏模式
                setRequestedOrientation(ActivityInfo.SCREEN_ORIENTATION_PORTRAIT);
            }
        });

        customNodeButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                drawPopupWindow.dismiss();
                // 启动 CustomNodeActivity
                Intent intent = new Intent(VideoPlayerActivity.this, CustomNodeActivity.class);
                startActivity(intent);
            }
        });

        preprocessButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                popupWindow.dismiss();
                drawPopupWindow.dismiss();
                // 启动 PreprocessActivity 并传递文件名
                Intent intent = new Intent(VideoPlayerActivity.this, PreprocessActivity.class);
                intent.putExtra("videoUri", videoUri.toString());
                intent.putExtra("totalDurationMs", player.getDuration());
                intent.putExtra("frameRate", player.getVideoFormat().frameRate);
                preprocessActivityLauncher.launch(intent);
            }
        });

        paintModeCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                playerPause();
                lineModeCheckbox.setChecked(false);
                drawView.setDrawingMode(DrawView.DrawingMode.PAINT);
//                }
                drawSettingsButton.setText("绘制: 笔");
                drawView.setDrawingEnabled(true);
            } else {
                drawSettingsButton.setText("绘制设置");
                drawView.setDrawingEnabled(false);
            }
            drawPopupWindow.dismiss();
        });


        lineModeCheckbox.setOnCheckedChangeListener((buttonView, isChecked) -> {
            if (isChecked) {
                playerPause();
//                if (playTextView != null) {
//                    playTextView.setText("暂停");
                paintModeCheckbox.setChecked(false);
                drawView.setDrawingMode(DrawView.DrawingMode.LINE);
//                }
                drawSettingsButton.setText("绘制: 线");
                drawView.setDrawingEnabled(true);
            } else {
                drawSettingsButton.setText("绘制设置");
                drawView.setDrawingEnabled(false);
            }
            drawPopupWindow.dismiss();
        });

        clearDrawButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                drawView.clear();
                drawPopupWindow.dismiss();
            }
        });

        // 设置按钮点击事件
        settingsButton.setOnClickListener(v -> {
            if (popupWindow.isShowing()) {
                popupWindow.dismiss();
            } else {
                // 显示 PopupWindow，从右上角弹出
                popupWindow.showAtLocation(v, Gravity.TOP | Gravity.END, 0, 0);
            }
        });

        drawSettingsButton.setOnClickListener(v -> {
            if (drawPopupWindow.isShowing()) {
                drawPopupWindow.dismiss();
            } else {
                // 获取按钮在屏幕上的位置
                int[] location = new int[2];
                v.getLocationOnScreen(location);
                int buttonX = location[0];  // 按钮左上角X坐标
                int buttonY = location[1];  // 按钮左上角Y坐标
                int buttonWidth = v.getWidth();
                int buttonHeight = v.getHeight();

                // 测量PopupWindow的实际宽高
                View pv = drawPopupWindow.getContentView();
                pv.measure(View.MeasureSpec.UNSPECIFIED, View.MeasureSpec.UNSPECIFIED);
                int popupWidth = pv.getMeasuredWidth();
                int popupHeight = pv.getMeasuredHeight();

                // 计算弹出位置：从按钮左下角开始向右上方弹出
                // X坐标：按钮左下角X坐标（按钮左上角X坐标）
                // Y坐标：按钮左下角Y坐标 - 弹出窗口高度（使弹出窗口向上展开）
                int x = buttonX;  // 左下角X坐标
                int y = buttonY + buttonHeight - popupHeight;  // 向上弹出

                // 确保弹窗不会超出屏幕右侧
                int screenWidth = getResources().getDisplayMetrics().widthPixels;
                if (x + popupWidth > screenWidth) {
                    x = screenWidth - popupWidth;  // 右对齐屏幕边缘
                }

                // 确保弹窗不会超出屏幕顶部
                if (y < 0) {
                    y = 0;  // 顶部对齐屏幕边缘
                }

                // 显示PopupWindow，使用绝对坐标定位
                drawPopupWindow.showAtLocation(v, Gravity.NO_GRAVITY, x, y);
            }
        });


        TrackSelector trackSelector = new DefaultTrackSelector(getApplicationContext());
        TrackSelectionParameters trackParams = new TrackSelectionParameters.Builder(getApplicationContext())
                .setMaxVideoSize(1920, 1080)
                .build();
        trackSelector.setParameters(trackParams);

        // 初始化 ExoPlayer
        player = new ExoPlayer.Builder(this)
                .setRenderersFactory(renderersFactory)
                .setTrackSelector(trackSelector)
                .setUsePlatformDiagnostics(false)
                .build();
//        player.setVideoTextureView(textureView);
//        playerView.setLayerType(View.LAYER_TYPE_SOFTWARE, null);
        playerView.setPlayer(player);

        videoUri = Uri.parse(videoUriStr);
        if (videoUriStr != null) {
            MediaItem mediaItem = MediaItem.fromUri(videoUri);
            MediaSource mediaSource = new ProgressiveMediaSource.Factory(cacheDataSourceFactory)
                    .createMediaSource(mediaItem);
//            player.setMediaItem(mediaItem);
            player.setMediaSource(mediaSource);
            player.prepare();
        }

        // 设置视频帧元数据监听器
        player.setVideoFrameMetadataListener(new VideoFrameMetadataListener() {
            @Override
            public void onVideoFrameAboutToBeRendered(long presentationTimeUs, long releaseTimeNs, Format format, @Nullable MediaFormat mediaFormat) {
//                processFrame(presentationTimeUs);
                currentPresentationTimeUs = presentationTimeUs;
                // 如果有未完成的任务，尝试取消它
                if (currentDetectionTask != null && !currentDetectionTask.isDone()) {
                    currentDetectionTask.cancel(true);
                }
                // 提交新的检测任务
                currentDetectionTask = detectionExecutorService.submit(() -> {
                    // 检查任务是否被取消
                    if (!Thread.currentThread().isInterrupted()) {
                        processFrame();
                    }
                });
//                detectionExecutorService.execute(() -> processFrame(presentationTimeUs));
            }

        });

        player.addListener(new Player.Listener() {
            @Override
            public void onPlaybackStateChanged(int playbackState) {
                if (playbackState == Player.STATE_READY) {

                    long durationMs = player.getDuration();
                    frameRate = player.getVideoFormat().frameRate;
                    totalFrames = (int) (durationMs * frameRate / 1000); // 总帧数

                    if (preprocessData.size() != totalFrames) {
                        loadPreprocessData();
                    }
                }

                if (playbackState == Player.EVENT_IS_LOADING_CHANGED) {
//                    if (frameWidth == 0 || frameHeight == 0) {
//                        int[] fixLine = getUnstretchedSize(((TextureView) playerView.getVideoSurfaceView()).getBitmap());
//                        frameWidth = fixLine[0];
//                        frameHeight = fixLine[1];
//                    }

                    isWaiting = false;
                }
                if (playbackState == Player.STATE_ENDED) {
                    // 视频播放完成，暂停播放
                    playerPause();
//                    if (playTextView != null) {
//                        playTextView.setText("暂停");
//                    }
                }
                Player.Listener.super.onPlaybackStateChanged(playbackState);
            }
        });

        freezeImageView = findViewById(R.id.freezeImageView);

//        playButton.setOnClickListener(new View.OnClickListener() {
//            @Override
//            public void onClick(View v) {
//                if (player.isPlaying()){
//                    player.pause();
//                    playButton.setText("播放");
//                } else {
//                    player.play();
//                    playButton.setText("暂停");
//                }
//            }
//        });

        nextFrameButton = findViewById(R.id.nextFrameButton);
        nextFrameButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (player!= null) {
                    long p = player.getCurrentPosition() + (long)(1000 / player.getVideoFormat().frameRate);
                    player.seekTo(p);
                }
            }
        });
        nextFrameButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View v) {
                longPressHandler.post(forwardRunnable);
                return true;
            }
        });
        nextFrameButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
                    longPressHandler.removeCallbacks(forwardRunnable);
                }
                return false;
            }
        });

        lastFrameButton = findViewById(R.id.lastFrameButton);
        lastFrameButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (player!= null) {
                    long p = player.getCurrentPosition() - (long) (1000 / player.getVideoFormat().frameRate);
                    player.seekTo(p);
                }
            }
        });
        lastFrameButton.setOnLongClickListener(new View.OnLongClickListener() {
            @Override
            public boolean onLongClick(View view) {
                longPressHandler.post(backwardRunnable);
                return true;
            }
        });
        lastFrameButton.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                if (event.getAction() == MotionEvent.ACTION_UP || event.getAction() == MotionEvent.ACTION_CANCEL) {
                    longPressHandler.removeCallbacks(backwardRunnable);
                }
                return false;
            }
        });

        // 设置按钮点击事件
        decreaseSpeedButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                decreasePlaybackRate();
            }
        });

        increaseSpeedButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                increasePlaybackRate();
            }
        });


        // 设置 SeekBar 监听器
        seekBar = findViewById(R.id.seekBar);
        seekBar.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() {
            @Override
            public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) {
                if (fromUser && player != null) {
                    long duration = player.getDuration();
                    if (duration > 0) {
                        long position = (long) ((float) duration * ((float) progress / 100.0f));
                        player.seekTo(position);
                        // 更新当前帧时间（微秒）
//                        processFrame(getIntent().getStringExtra("videoUri"));
                    }
                }
            }
//                handler.post(updateSeekBarRunnable);

        @Override
        public void onStartTrackingTouch(SeekBar seekBar) {
            player.pause();
        }

        @Override
        public void onStopTrackingTouch(SeekBar seekBar) {
            if (playPauseButton.getText().equals("暂停")) {
                player.play();
            }
//                processFrame();
//                handler.post(updateSeekBarRunnable);
        }

    });

    // 开始更新 SeekBar
        handler.post(updateSeekBarRunnable);
        // 启动检查任务
        checkSharedPrefsHandler.post(checkSharedPrefsRunnable);

        // 初始化 GestureDetector
//        gestureDetector = new GestureDetector(this, new GestureListener());

        FrameLayout touchLayout = findViewById(R.id.touchLayout);
        touchLayout.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction() & MotionEvent.ACTION_MASK) {
                    case MotionEvent.ACTION_DOWN:
                        lastX = event.getX();
                        lastY = event.getY();
                        mode = DRAG;
                        break;
                    case MotionEvent.ACTION_POINTER_DOWN:
                        oldDist = spacing(event);
                        if (oldDist > 10f) {
                            mode = ZOOM;
                        }
                        break;
                    case MotionEvent.ACTION_MOVE:
                        if (mode == DRAG) {
                            dx = event.getX() - lastX;
                            dy = event.getY() - lastY;
                            moveViews(dx, dy);
                            lastX = event.getX();
                            lastY = event.getY();
                        } else if (mode == ZOOM) {
                            float newDist = spacing(event);
                            if (newDist > 10f) {
                                float newScale = scale * (newDist / oldDist);
                                // 检查是否接近最小缩放比例
                                if (newScale <= MIN_SCALE + 0.01f) {
                                    resetViewsToInitialState();
                                    scale = initialScale;
                                } else {
                                    newScale = Math.max(MIN_SCALE, Math.min(newScale, MAX_SCALE));
                                    scale = newScale;
                                    scaleViews(scale);
                                }
                                oldDist = newDist;
                            }
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_POINTER_UP:
                        mode = NONE;
                        break;
                }
                return true;
            }
        });


        replayTagButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                long currentPosition = player.getCurrentPosition();
                if (currentPosition <= replayStartTime){
                    replayStartTime = -1;
                }
                if (replayStartTime == -1) {
                    replayStartTime = currentPosition;
                    replayTagButton.setText("回放终点");
                } else if (replayEndTime == -1) {
                    replayEndTime = currentPosition;
                    replayTagButton.setText("回放清除");
                    replayButton.setEnabled(true);
                } else {
                    replayStartTime = -1;
                    replayEndTime = -1;
                    replayTagButton.setText("回放起点");
                    replayButton.setEnabled(false);
                }
                replayTextView.setText("回放：" + replayStartTime + "ms --> " + replayEndTime + "ms");
            }
        });

        replayButton.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                if (player!= null) {
                    isReplay = true;
                    player.pause();
                    player.seekTo(replayStartTime);
                    playerPlay();
//                    playTextView.setText("播放");
                }
            }
        });

        drawView.setOnTouchListener(new View.OnTouchListener() {
            @Override
            public boolean onTouch(View v, MotionEvent event) {
                switch (event.getAction()) {
                    case MotionEvent.ACTION_DOWN:
                        playerPause();
                        if (drawView.isDrawingEnabled()) {
//                            Bitmap frame = ((TextureView) playerView.getVideoSurfaceView()).getBitmap();
                            Bitmap frame = getFrameBitmap(player.getCurrentPosition() * 1000);
                            if (frame != null) {
                                // 获取内容区域的尺寸
                                android.graphics.Rect rect = new android.graphics.Rect();
                                getWindow().getDecorView().getWindowVisibleDisplayFrame(rect);
                                int contentWidth = rect.width();
                                int contentHeight = rect.height();
                                // 创建一个与屏幕尺寸相同的空白 Bitmap
                                originalVideoBitmap = Bitmap.createBitmap(contentWidth, contentHeight, Bitmap.Config.ARGB_8888);
                                Canvas canvas = new Canvas(originalVideoBitmap);
                                // 计算视频 Bitmap 的绘制位置，使其居中
                                int x = (contentWidth - frame.getWidth()) / 2;
                                int y = (contentHeight - frame.getHeight()) / 2;
                                // 将视频 Bitmap 绘制到空白 Bitmap 的中央
                                canvas.drawBitmap(frame, x, y, null);
                            }
                        }

                    case MotionEvent.ACTION_MOVE:
                        float x = event.getX();
                        float y = event.getY();
                        if (drawView.isDrawingEnabled()) {
                            showMagnifier(x, y);
                        }
                        break;
                    case MotionEvent.ACTION_UP:
                    case MotionEvent.ACTION_CANCEL:
                        hideMagnifier();
                        break;
                }
                return false;
            }
        });


        // 记录初始状态
        initialScale = scale;
        initialTranslationX = playerView.getTranslationX();
        initialTranslationY = playerView.getTranslationY();
//        textureView = ((TextureView) playerView.getVideoSurfaceView());


        preprocessActivityLauncher = registerForActivityResult(
                new ActivityResultContracts.StartActivityForResult(),
                result -> {
                    // 当 PreprocessActivity 完成并返回时触发
//                    if (result.getResultCode() == Activity.RESULT_OK) {
                        // 重新加载预处理数据（此时文件已更新）
                        loadPreprocessData();
//                    }
                }
        );


    }

    private float spacing(MotionEvent event) {
        float x = event.getX(0) - event.getX(1);
        float y = event.getY(0) - event.getY(1);
        return (float) Math.sqrt(x * x + y * y);
    }

    private void moveViews(float dx, float dy) {
        playerView.setTranslationX(playerView.getTranslationX() + dx);
        playerView.setTranslationY(playerView.getTranslationY() + dy);
//        actionLineView.setTranslationX(actionLineView.getTranslationX() + dx);
//        actionLineView.setTranslationY(actionLineView.getTranslationY() + dy);
        drawView.setTranslationX(drawView.getTranslationX() + dx);
        drawView.setTranslationY(drawView.getTranslationY() + dy);
        freezeImageView.setTranslationX(freezeImageView.getTranslationX() + dx);
        freezeImageView.setTranslationY(freezeImageView.getTranslationY() + dy);
    }

    private void resetViewsToInitialState() {
        // 恢复缩放比例
        playerView.setScaleX(initialScale);
        playerView.setScaleY(initialScale);
//        actionLineView.setScaleX(initialScale);
//        actionLineView.setScaleY(initialScale);
        drawView.setScaleX(initialScale);
        drawView.setScaleY(initialScale);
        freezeImageView.setScaleX(initialScale);
        freezeImageView.setScaleY(initialScale);

        // 恢复位置
        playerView.setTranslationX(initialTranslationX);
        playerView.setTranslationY(initialTranslationY);
//        actionLineView.setTranslationX(initialTranslationX);
//        actionLineView.setTranslationY(initialTranslationY);
        drawView.setTranslationX(initialTranslationX);
        drawView.setTranslationY(initialTranslationY);
        freezeImageView.setTranslationX(initialTranslationX);
        freezeImageView.setTranslationY(initialTranslationY);
    }

    private void scaleViews(float scale) {
        playerView.setScaleX(scale);
        playerView.setScaleY(scale);
//        actionLineView.setScaleX(scale);
//        actionLineView.setScaleY(scale);
        drawView.setScaleX(scale);
        drawView.setScaleY(scale);
        freezeImageView.setScaleX(scale);
        freezeImageView.setScaleY(scale);
    }


    public int[] getUnstretchedSize(Bitmap bitmap) {
        int oriWidth = bitmap.getWidth();
        int oriHeight = bitmap.getHeight();
        int width = (int)(oriWidth * 0.5);
        int height = (int)(oriHeight * 0.5);

        ArrayList<Integer> samePixelsInWidthList = new ArrayList<>();
        ArrayList<Integer> samePixelsInHeightList = new ArrayList<>();

        for (int y = 0; y < height; y++) {
            for (int x = oriWidth - 1; x > 0; x--) {
                int currentPixel = bitmap.getPixel(x, y);
                int prevPixel = bitmap.getPixel(x - 1, y);
                if (currentPixel != prevPixel) {
                    samePixelsInWidthList.add(x);
                    break;
                }
            }
        }
        int maxSamePixelsInWidth = getMostFrequentElement(samePixelsInWidthList);
        for (int x = 0; x < width; x++) {
            for (int y = oriHeight - 1; y > 0; y--) {
                int currentPixel = bitmap.getPixel(x, y);
                int prevPixel = bitmap.getPixel(x, y - 1);
                if (currentPixel != prevPixel) {
                    samePixelsInHeightList.add(y);
                    break;
                }
            }
        }
        int maxSamePixelsInHeight = getMostFrequentElement(samePixelsInHeightList);
        Log.e("@@@@@getUnstretchedSize", maxSamePixelsInWidth + " "+maxSamePixelsInHeight);
        return new int[]{maxSamePixelsInWidth, maxSamePixelsInHeight};
    }

    private Integer getMostFrequentElement(ArrayList<Integer> list) {
        if (list == null || list.isEmpty()) {
            return null;
        }

        // 使用 HashMap 统计每个元素的出现次数
        Map<Integer, Integer> frequencyMap = new HashMap<>();
        for (Integer num : list) {
            frequencyMap.put(num, frequencyMap.getOrDefault(num, 0) + 1);
        }

        // 找出出现次数最多的元素
        Integer mostFrequent = null;
        int maxFrequency = 0;
        for (Map.Entry<Integer, Integer> entry : frequencyMap.entrySet()) {
            if (entry.getValue() > maxFrequency) {
                maxFrequency = entry.getValue();
                mostFrequent = entry.getKey();
            }
        }

        return mostFrequent;
    }

    private void setFullScreen() {
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.R) {
            // Android 11 (API 30) 及以上版本
            getWindow().setDecorFitsSystemWindows(false);
            View decorView = getWindow().getDecorView();
            int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            decorView.setSystemUiVisibility(flags);
        } else if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.KITKAT) {
            // Android 4.4 (API 19) 到 Android 10 (API 29)
            View decorView = getWindow().getDecorView();
            int flags = View.SYSTEM_UI_FLAG_LAYOUT_STABLE
                    | View.SYSTEM_UI_FLAG_LAYOUT_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_LAYOUT_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_HIDE_NAVIGATION
                    | View.SYSTEM_UI_FLAG_FULLSCREEN
                    | View.SYSTEM_UI_FLAG_IMMERSIVE_STICKY;
            decorView.setSystemUiVisibility(flags);
        } else {
            // Android 4.4 以下版本
            View decorView = getWindow().getDecorView();
            int flags = View.SYSTEM_UI_FLAG_FULLSCREEN;
            decorView.setSystemUiVisibility(flags);
        }
    }

    private void processFrame() {
        if (preprocessData.size() > 0) {
            int frameIndex = -1;
            if (player != null) {
                try {
                    frameIndex = (int)(currentPresentationTimeUs * frameRate / 1000000); // 核心计算公式
                    frameIndex = Math.max(0, Math.min(frameIndex, totalFrames - 1)); // 限制范围
                    // 示例：使用帧数获取预处理数据
                    List<NormalizedLandmark> preprocessLandmarks = preprocessData.get(frameIndex);
                    if (preprocessLandmarks != null) {
                        // 可在此处使用预处理的坐标数据（如绘制、计算等）
                        processLandmarkers(preprocessLandmarks);
                    }
                    actionLineView.invalidate();
                } catch (Exception e) {
                    e.printStackTrace();
                }
            }
        } else {
            Bitmap frame = ((TextureView) playerView.getVideoSurfaceView()).getBitmap();
//        Bitmap frame = getFrameBitmap(timestampMs);
            if (frame != null) {
//            Log.e("@@@@@executorService", "processFrame: " + timestampMs);
//            Bitmap frameBitmap = Bitmap.createScaledBitmap(frame, 224, 224, true);
//            Bitmap argb8888Frame = frameBitmap.copy(Bitmap.Config.ARGB_8888, false);
//            if (frameBitmap.getConfig() == Bitmap.Config.ARGB_8888) {
//                argb8888Frame = frameBitmap.copy(Bitmap.Config.ARGB_8888, false);
//            } else {
//                argb8888Frame = frameBitmap;
//            }
//            if (frame.getConfig() != Bitmap.Config.ARGB_8888) {
//                frame = frame.copy(Bitmap.Config.ARGB_8888, false);
//            }
                MPImage mpImage = new BitmapImageBuilder(frame).build();
//                PoseLandmarkerResult result = poseLandmarker.detectForVideo(mpImage, timestampMs);
                poseLandmarker.detectAsync(mpImage, SystemClock.uptimeMillis());

            }
        }
    }

    private PointF getJointPosition(NormalizedLandmark landmark) {
        float offsetX = (playerView.getWidth() - playerView.getVideoSurfaceView().getWidth()) / 2;
        float offsetY = (playerView.getHeight() - playerView.getVideoSurfaceView().getHeight()) / 2;
        float x = offsetX + (landmark.x() * ((TextureView) playerView.getVideoSurfaceView()).getWidth());
        float y = offsetY + (landmark.y() *  ((TextureView) playerView.getVideoSurfaceView()).getHeight());
        return new PointF(x, y);
    }

    private List<PointF> convertLandmarkToJointPoints(List<NormalizedLandmark> landmarks) {
        List<PointF> points = new ArrayList<>();
        // 遍历 nodeStates 中的键
        for (Map.Entry<Integer, Boolean> entry : nodeStates.entrySet()) {
            int index = entry.getKey();
            boolean isEnabled = entry.getValue();
            if (index == 0){
                continue;
            }
            // 检查节点状态是否为 true 且索引在 landmarks 列表范围内
            if (isEnabled) {
                NormalizedLandmark landmark = landmarks.get(index);
                points.add(getJointPosition(landmark));
            }
        }
        return points;
    }

    private List<PointF> convertLandmarkToPathPoints(List<NormalizedLandmark> landmarks) {
        List<PointF> points = new ArrayList<>();
        for (int i : Utils.KEY_IDS) {
            if (nodeStates.get(i)) {
                NormalizedLandmark landmark = landmarks.get(i);
                points.add(getJointPosition(landmark));
            } else {
                points.add(null);
            }
        }
        return points;
    }

    private List<PointF[]> convertLandmarkToLines(List<NormalizedLandmark> landmarks) {
        List<PointF[]> lines = new ArrayList<>();
        int[][] connections = {
                {11, 12},
                {11, 13}, {13, 15},
                {12, 14}, {14, 16},
                {11, 23}, {12, 24},
                {23, 24}
        };

        for (int[] connection : connections) {
            int startIndex = connection[0];
            int endIndex = connection[1];
            if (nodeStates.get(startIndex) && nodeStates.get(endIndex)) {
                PointF startPoint = getJointPosition(landmarks.get(startIndex));
                PointF endPoint = getJointPosition(landmarks.get(endIndex));
                PointF[] line = new PointF[]{startPoint, endPoint};
                lines.add(line);
            }
        }

        return lines;
    }

    private Bitmap getFrameBitmap(long currentPosition) {
        MediaMetadataRetriever retriever = new MediaMetadataRetriever();
        retriever.setDataSource(this, videoUri);
        Bitmap frameBitmap = retriever.getFrameAtTime(currentPosition, MediaMetadataRetriever.OPTION_CLOSEST);
        if (frameBitmap == null) {
            frameBitmap = ((TextureView) playerView.getVideoSurfaceView()).getBitmap();
        }

        // 如果freezeImageView已初始化且尺寸有效，应用fitCenter缩放
        if (freezeImageView != null && freezeImageView.getWidth() > 0 && freezeImageView.getHeight() > 0) {
            int targetWidth = freezeImageView.getWidth();
            int targetHeight = freezeImageView.getHeight();

            // 计算原始bitmap的宽高比
            float originalRatio = (float) frameBitmap.getWidth() / frameBitmap.getHeight();
            // 计算目标区域的宽高比
            float targetRatio = (float) targetWidth / targetHeight;

            int newWidth, newHeight;

            // 根据比例确定缩放后的尺寸（fitCenter逻辑）
            if (originalRatio > targetRatio) {
                // 原始图片更宽，按宽度缩放
                newWidth = targetWidth;
                newHeight = (int) (targetWidth / originalRatio);
            } else {
                // 原始图片更高，按高度缩放
                newHeight = targetHeight;
                newWidth = (int) (targetHeight * originalRatio);
            }

            // 缩放bitmap并保持高质量
            frameBitmap = Bitmap.createScaledBitmap(frameBitmap, newWidth, newHeight, true);
        }

        return frameBitmap;
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        handler.removeCallbacks(updateSeekBarRunnable);
        // 移除检查任务
        checkSharedPrefsHandler.removeCallbacks(checkSharedPrefsRunnable);
        player.release();
        if (poseLandmarker!= null) {
            poseLandmarker.close();
        }
        // 关闭线程池
        if (detectionExecutorService != null) {
            detectionExecutorService.shutdown();
        }
    }

    @Override
    public void onConfigurationChanged(@NonNull Configuration newConfig) {
        super.onConfigurationChanged(newConfig);
//        player.setVideoTextureView(textureView);
    }

    private void processLandmarkers(List<NormalizedLandmark> landmarks){
        List<PointF> jointPoints = convertLandmarkToJointPoints(landmarks);
        List<PointF[]> lines = convertLandmarkToLines(landmarks);
        List<PointF> pathPoints = convertLandmarkToPathPoints(landmarks);
        actionLineView.setCircles(jointPoints);
        actionLineView.setLines(lines);
        actionLineView.addPathPoints(pathPoints);

        if (landmarks.size() > 16) { // 确保关键点索引有效
            PointF p11 = getJointPosition(landmarks.get(11)); // 左肩
            PointF p12 = getJointPosition(landmarks.get(12)); // 右肩
            PointF p13 = getJointPosition(landmarks.get(13)); // 左肘
            PointF p14 = getJointPosition(landmarks.get(14)); // 右肘
            PointF p15 = getJointPosition(landmarks.get(15)); // 左手腕
            PointF p16 = getJointPosition(landmarks.get(16)); // 右手腕

            // 计算各角度
            double angle1 = Utils.calculateAngle(p12, p11, p13); // {11, 12}和{11, 13}的角度
            if (p13.y > p11.y) {
                angle1 = 360 - angle1;
            }
            double angle2 = Utils.calculateAngle(p11, p12, p14); // {11, 12}和{12, 14}的角度
            if (p14.y > p12.y) {
                angle2 = 360 - angle2;
            }
            double angle3 = Utils.calculateAngle(p11, p13, p15); // {11, 13}和{13, 15}的夹角
            double angle4 = Utils.calculateAngle(p12, p14, p16); // {12, 14}和{14, 16}的夹角
            double finalAngle = angle1;
            double finalAngle1 = angle2;
            runOnUiThread(() -> {
                leftShoulderTextView.setText(String.format("%.2f°", finalAngle));
                rightShoulderTextView.setText(String.format("%.2f°", finalAngle1));
                leftElbowTextView.setText(String.format("%.2f°", angle3));
                rightElbowTextView.setText(String.format("%.2f°", angle4));
            });

            // 可以在这里使用角度值，例如打印日志或传递给视图显示
//            Log.d("AngleCalculation", String.format(
//                    "角度1: %.2f°, 角度2: %.2f°, 角度3: %.2f°, 角度4: %.2f°",
//                    angle1, angle2, angle3, angle4
//            ));
        }

        if (nodeStates.get(0)) {
            actionLineView.setHeadPoint(getJointPosition(landmarks.get(0)));
            actionLineView.setEyePoints(getJointPosition(landmarks.get(1)), getJointPosition(landmarks.get(2)));
        } else {
            actionLineView.setHeadPoint(null);
            actionLineView.setEyePoints(null, null);
        }
        actionLineView.setShoulders(getJointPosition(landmarks.get(11)), getJointPosition(landmarks.get(12)));
    }

    public void loadMPModel(String selectedModel) {
        // 模型文件在assets目录下的文件名
        String modelName = String.format("pose_landmarker_%s.task", selectedModel);
        BaseOptions.Builder baseOptionsBuilder = BaseOptions.builder();
        baseOptionsBuilder.setDelegate(Delegate.GPU);
        baseOptionsBuilder.setModelAssetPath(modelName);
        PoseLandmarker.PoseLandmarkerOptions.Builder optionsBuilder = PoseLandmarker.PoseLandmarkerOptions.builder();
        OutputHandler.ResultListener<PoseLandmarkerResult, MPImage> returnLivestreamResult = new OutputHandler.ResultListener<PoseLandmarkerResult, MPImage>() {
            @Override
            public void run(PoseLandmarkerResult result, MPImage input) {
                List<List<NormalizedLandmark>> landmarks_lst = result.landmarks();
                landmarks_lst = Utils.applyFilter(previousLandmarks, landmarks_lst);
//                Log.e("@@@@@landmarks", "landmarks: " + landmarks_lst.size());
                for (List<NormalizedLandmark> landmarks : landmarks_lst) {
                    processLandmarkers(landmarks);
//                    List<PointF> jointPoints = convertLandmarkToJointPoints(landmarks);
//                    List<PointF[]> lines = convertLandmarkToLines(landmarks);
//                    List<PointF> pathPoints = convertLandmarkToPathPoints(landmarks);
//                    actionLineView.setCircles(jointPoints);
//                    actionLineView.setLines(lines);
//                    actionLineView.addPathPoints(pathPoints);
//                    if (nodeStates.get(0)) {
//                        actionLineView.setHeadPoint(getJointPosition(landmarks.get(0)));
//                        actionLineView.setEyePoints(getJointPosition(landmarks.get(1)), getJointPosition(landmarks.get(2)));
//                    } else {
//                        actionLineView.setHeadPoint(null);
//                        actionLineView.setEyePoints(null, null);
//                    }
//                    actionLineView.setShoulders(getJointPosition(landmarks.get(11)), getJointPosition(landmarks.get(12)));
                }
                actionLineView.invalidate();
            }
        };
        optionsBuilder.setBaseOptions(baseOptionsBuilder.build())
                .setMinPoseDetectionConfidence(0.8f)
                .setMinTrackingConfidence(0.9f)
                .setMinPosePresenceConfidence(0.8f)
                .setNumPoses(1)
                .setOutputSegmentationMasks(false)
                .setResultListener(returnLivestreamResult)
                .setRunningMode(RunningMode.LIVE_STREAM);
        PoseLandmarker.PoseLandmarkerOptions poseLandmarkerOptions = optionsBuilder.build();
        poseLandmarker = PoseLandmarker.createFromOptions(getApplicationContext(), poseLandmarkerOptions);
    }


//    private class GestureListener extends GestureDetector.SimpleOnGestureListener {
//        private static final int SWIPE_THRESHOLD = 100;
//        private static final int SWIPE_VELOCITY_THRESHOLD = 100;
//
//        @Override
//        public boolean onFling(MotionEvent e1, MotionEvent e2, float velocityX, float velocityY) {
//            float diffX = e2.getX() - e1.getX();
//            float diffY = e2.getY() - e1.getY();
//
//            if (Math.abs(diffX) > Math.abs(diffY)) {
//                // 左右滑动
////                if (Math.abs(diffX) > SWIPE_THRESHOLD && Math.abs(velocityX) > SWIPE_VELOCITY_THRESHOLD) {
////                    if (diffX > 0) {
////                        // 向右滑动，快退
////                        seekForward();
////                    } else {
////                        // 向左滑动，快进
////                        seekBackward();
////                    }
////                    return true;
////                }
//            } else {
//                // 上下滑动
//                if (moveStatus == -1) {
//                    if (diffY > 0) {
//                        // 向下滑动，降低播放倍率
//                        decreasePlaybackRate();
//                    } else {
//                        // 向上滑动，提高播放倍率
//                        increasePlaybackRate();
//                    }
//                    return true;
//                }
//            }
//            return false;
//        }
//
//        @Override
//        public boolean onDoubleTap(MotionEvent e) {
//            if (player != null) {
//                if (player.isPlaying()) {
//                    player.pause();
//                    playTextView.setText("暂停");
//                } else {
//                    if (player.getCurrentPosition() >= player.getDuration()){
//                        player.seekTo(0);
//                    }
//                    player.play();
//                    playTextView.setText("播放");
//                }
//            }
//            return true;
//        }
//    }


//    private void seekForward() {
//        if (player != null) {
//            long currentPosition = player.getCurrentPosition();
//            long newPosition = currentPosition + PROGRESS_INCREMENT;
//            long duration = player.getDuration();
//            if (newPosition > duration) {
//                newPosition = duration;
//            }
//            player.seekTo(newPosition);
//        }
//    }
//
//    private void seekBackward() {
//        if (player != null) {
//            long currentPosition = player.getCurrentPosition();
//            long newPosition = currentPosition - PROGRESS_INCREMENT;
//            if (newPosition < 0) {
//                newPosition = 0;
//            }
//            player.seekTo(newPosition);
//        }
//    }

    private void playerPause(){
        if (player != null) {
            player.pause();
            playPauseButton.setText("播放");
            playPauseButton.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.teal_200));
        }
    }

    private void playerPlay(){
        if (player != null) {
            player.play();
            playPauseButton.setText("暂停");
            playPauseButton.setBackgroundColor(ContextCompat.getColor(getApplicationContext(), R.color.teal_700));
        }
    }

    private void increasePlaybackRate() {
        if (player != null) {
            currentSpeedIdx = Math.min(currentSpeedIdx + 1, speedList.length - 1);
            float newRate = speedList[currentSpeedIdx];
            PlaybackParameters playbackParameters = new PlaybackParameters(newRate, newRate);
            player.setPlaybackParameters(playbackParameters);
            playbackRateTextView.setText(String.format(newRate + "x"));
//            player.setPlaybackSpeed(newRate);
        }
    }

    private void decreasePlaybackRate() {
        if (player != null) {
            currentSpeedIdx = Math.max(currentSpeedIdx - 1, 0);
            float newRate = speedList[currentSpeedIdx];
            PlaybackParameters playbackParameters = new PlaybackParameters(newRate, newRate);
            player.setPlaybackParameters(playbackParameters);
            playbackRateTextView.setText(String.format(newRate + "x"));
        }
    }

    // 显示放大镜
    private void showMagnifier(float x, float y) {
        magnifierImageView.setVisibility(View.VISIBLE);

        // 获取画布的 Bitmap
        drawView.setDrawingCacheEnabled(true);
        Bitmap originalDrawBitmap = drawView.getDrawingCache();

        // 获取当前视频帧的 Bitmap

        if (originalDrawBitmap != null || originalVideoBitmap != null) {
            // 确定最大宽度和高度
            int maxWidth = 0;
            int maxHeight = 0;
            if (originalDrawBitmap != null) {
                maxWidth = originalDrawBitmap.getWidth();
                maxHeight = originalDrawBitmap.getHeight();
            }
            if (originalVideoBitmap != null) {
                maxWidth = Math.max(maxWidth, originalVideoBitmap.getWidth());
                maxHeight = Math.max(maxHeight, originalVideoBitmap.getHeight());
            }

            // 创建一个合并的 Bitmap
            Bitmap combinedBitmap = Bitmap.createBitmap(maxWidth, maxHeight, Bitmap.Config.ARGB_8888);
            Canvas canvas = new Canvas(combinedBitmap);

            // 绘制视频帧 Bitmap 并居中
            canvas.drawBitmap(originalVideoBitmap, 0, 0, null);

            // 绘制画布 Bitmap
            if (originalDrawBitmap != null) {
                canvas.drawBitmap(originalDrawBitmap, 0, 0, null);
            }

            // 计算截取区域
            int left = (int) (x - MAGNIFIER_SIZE / 2);
            int top = (int) (y - MAGNIFIER_SIZE / 2);
            int right = left + MAGNIFIER_SIZE;
            int bottom = top + MAGNIFIER_SIZE;

            // 确保截取区域在合并后的 Bitmap 范围内
            left = Math.max(0, left);
            top = Math.max(0, top);
            right = Math.min(maxWidth, right);
            bottom = Math.min(maxHeight, bottom);

            // 截取局部 Bitmap
            Bitmap combinedCroppedBitmap = Bitmap.createBitmap(combinedBitmap, left, top, right - left, bottom - top);

            if (combinedCroppedBitmap != null) {
                // 放大 Bitmap
                Matrix matrix = new Matrix();
                matrix.postScale(MAGNIFICATION_FACTOR, MAGNIFICATION_FACTOR);
                Bitmap scaledBitmap = Bitmap.createBitmap(combinedCroppedBitmap, 0, 0, combinedCroppedBitmap.getWidth(), combinedCroppedBitmap.getHeight(), matrix, true);

                // 显示放大后的 Bitmap
                magnifierImageView.setImageBitmap(scaledBitmap);

                // 获取屏幕宽度和高度
                int screenWidth = getResources().getDisplayMetrics().widthPixels;
                int screenHeight = getResources().getDisplayMetrics().heightPixels;

                // 获取放大镜的宽度和高度
                int magnifierWidth = magnifierImageView.getWidth();
                int magnifierHeight = magnifierImageView.getHeight();

                // 计算放大镜的位置，避免移出屏幕
                float magnifierX = x - (magnifierWidth * 3 / 5);
                float magnifierY = y - (magnifierHeight * 3 / 5);

                // 限制 x 坐标在屏幕范围内
                magnifierX = Math.max(0, Math.min(magnifierX, screenWidth - magnifierWidth));

                // 限制 y 坐标在屏幕范围内
                magnifierY = Math.max(0, Math.min(magnifierY, screenHeight - magnifierHeight));

                // 设置放大镜位置
                magnifierImageView.setX(magnifierX);
                magnifierImageView.setY(magnifierY);
            }
        }

        drawView.setDrawingCacheEnabled(false);
    }

    private void loadPreprocessData() {
        // 清空原有数据，避免重复加载
        preprocessData = Utils.loadPreprocessData(getApplicationContext(), videoUri);
        if (preprocessData.size() == totalFrames) {
            runOnUiThread(() -> {
                Toast.makeText(VideoPlayerActivity.this, "预处理完成，数据已加载", Toast.LENGTH_LONG).show();
                seekBarBackground.setVisibility(View.VISIBLE);
            });
        } else {
            preprocessData.clear();
            runOnUiThread(() -> {
                Toast.makeText(VideoPlayerActivity.this, "无预处理数据，实时分析", Toast.LENGTH_LONG).show();
                seekBarBackground.setVisibility(View.INVISIBLE);
            });
        }
    }
    private void hideMagnifier() {
        magnifierImageView.setVisibility(View.INVISIBLE);
        magnifierImageView.setImageBitmap(null);
    }

}